﻿using MhAdmin.SqlSugar.Extension;
using MimeKit;

namespace MhAdmin.System;

/// <summary>
/// <inheritdoc cref="IEmailService"/>
/// </summary>
public class EmailService : DbRepository<MsgMail>, IEmailService
{
    private readonly ISysUserService _sysUserService;
    private readonly IConfigService _configService;

    public EmailService(ISysUserService sysUserService, IConfigService configService)
    {
        _sysUserService = sysUserService;
        _configService = configService;
    }

    #region 查询

    /// <inheritdoc />
    public async Task<SqlSugarPagedList<MsgMail>> Page(EmailPageInput input)
    {
        var query = await GetQuery(input);
        return await query.ToPagedListAsync(input.Current, input.Size);
    }

    /// <inheritdoc />
    public async Task<List<MsgMail>> List(EmailPageInput input)
    {
        var query = await GetQuery(input);
        return await query.ToListAsync();
    }

    /// <inheritdoc />
    public async Task<MsgMail> Detail(BaseIdInput input)
    {
        var rules = await GetFirstAsync(it => it.Id == input.Id);

        //获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();
        if (dataScope.Count > 0 && (!dataScope.Contains(rules.CreateOrgId) || rules.CreateUserId != UserManager.UserId))//判断机构ID是否在数据范围或者创建人是否为当前登录人
            throw Oops.Bah("您没有权限查看该数据");

        return rules;
    }

    #endregion 查询

    #region 删除

    /// <inheritdoc />
    public async Task Delete(List<BaseIdInput> input)
    {
        //获取所有ID
        var ids = input.Select(it => it.Id).ToList();

        if (ids.Count > 0)
        {
            // 获取数据范围
            var dataScope = await _sysUserService.GetLoginUserApiDataScope();

            // 查询出所有数据
            var rules = await GetListAsync(it => ids.Contains(it.Id), it => new MsgMail { CreateOrgId = it.CreateOrgId, CreateUserId = it.CreateUserId });//根据ID获取机构ID和创建者ID

            // 判断是否都符合需求
            if (dataScope != null && !rules.Any(it => !dataScope.Contains(it.CreateOrgId) && it.CreateUserId != UserManager.UserId)) throw Oops.Bah(ErrorCodeEnum.A0004);

            // 删除数据
            await Context.FalseDeleteAsync<MsgMail>(ids);
        }
    }

    #endregion 删除

    #region 本地邮件

    /// <inheritdoc />
    public async Task<bool> SendLocalTxt(EmailLocalSendInput input)
    {
        // 获取发件人
        var sender = await GetLocalSender();

        // 构建收件人
        var receiver = input.ReceiverMail.Split(';').ToList();
        List<MailboxAddress> tos = new();
        foreach (var mail in receiver)
        {
            tos.Add(new MailboxAddress(mail, mail));
        }

        try
        {
            // 发送邮件
            await LocalEmailUtils.SendTxtEmail(sender, tos, input.MailSubject, input.MailBody);
            return await SaveMessage(sender, input, null, false);
        }
        catch (Exception ex)
        {
            return await SaveMessage(sender, input, ex, false);
        }
    }

    /// <inheritdoc />
    public async Task<bool> SendLocalHtml(EmailLocalSendInput input)
    {
        // 获取发件人
        var sender = await GetLocalSender();

        // 构建收件人
        var receiver = input.ReceiverMail.Split(';').ToList();
        List<MailboxAddress> tos = new();
        foreach (var mail in receiver)
        {
            tos.Add(new MailboxAddress(mail, mail));
        }

        try
        {
            // 发送邮件
            await LocalEmailUtils.SendHtmlEmail(sender, tos, input.MailSubject, input.MailBody);
            return await SaveMessage(sender, input, null, true);
        }
        catch (Exception ex)
        {
            return await SaveMessage(sender, input, ex, true);
        }
    }

    // 保存邮件发送信息
    private async Task<bool> SaveMessage(MailSender sender, EmailLocalSendInput input, Exception? ex, bool isHtml = false)
    {
        MsgMail msg = new()
        {
            MailType = CateGoryConst.Config_EMAIL_LOCAL,
            SendType = isHtml ? "HTML" : "TXT",
            SenderMail = sender.Address,
            ReceiverMail = input.ReceiverMail,
            ExeStatus = ex == null ? "发送成功" : "发送失败",
            ErrorMsg = ex?.Message ?? "",
            MailSubject = input.MailSubject,
            MailBody = input.MailBody
        };

        return await InsertAsync(msg);
    }

    #endregion 本地邮件

    #region 方法

    private async Task<MailSender> GetLocalSender()
    {
        //获取配置
        var address = await _configService.GetByConfigKey(CateGoryConst.Config_EMAIL_LOCAL, DevConfigConst.EMAIL_LOCAL_FROM) ?? throw Oops.Bah("未配置发送邮箱地址");

        var password = await _configService.GetByConfigKey(CateGoryConst.Config_EMAIL_LOCAL, DevConfigConst.EMAIL_LOCAL_PASSWORD) ?? throw Oops.Bah("未配置发送邮箱密码");

        return new MailSender(address.ConfigValue, password.ConfigValue);
    }

    private async Task<ISugarQueryable<MsgMail>> GetQuery(EmailPageInput input)
    {
        //获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();
        //动态查询条件,如果是连表查询,里面的it要改成连表里对应的别名
        var exp = Expressionable.Create<MsgMail>();
        //用户机构在数据范围内
        exp.AndIF(dataScope is { Count: > 0 }, it => dataScope.Contains(it.CreateOrgId));
        //默认创建者ID等于自己,根据实际情况修改条件
        exp.AndIF(dataScope is { Count: 0 }, it => it.CreateUserId == UserManager.UserId);

        exp.AndIF(!string.IsNullOrEmpty(input.MailType), x => x.MailType == input.MailType);

        exp.AndIF(!string.IsNullOrEmpty(input.MailSubject), x => x.MailSubject.Contains(input.MailSubject));

        return Context.Queryable<MsgMail>().Where(exp.ToExpression()).OrderByDescending(x => x.CreateTime);
    }

    #endregion 方法
}
